package org.deng.learn.concurrent.basic;

/**
 * @author 邓力宾
 * @date 2020/5/15 下午4:22
 * @desc
 * 锁池：某个线程中调用了对象锁的notify()方法之后，争夺执行权，进入锁池。
 *      如果另外的一个线程调用了相同对象的notifyAll()方法，那么处于该对象的等待池中的线程就会全部进入该对象的锁池中，准备争夺锁的拥有权。
 *       如果另外的一个线程调用了相同对象的notify()方法，那么仅仅有一个处于该对象的等待池中的线程(随机)会进入该对象的锁池。
 * 等待池：某个线程中调用了对象锁的wait()方法之后，该线程主动放弃执行权并等待唤醒，进入待待池。
 *          假设一个线程A调用了某个对象的wait()方法，线程A就会释放该对象的锁(因为wait()方法必须出现在synchronized中，
 *          这样自然在执行wait()方法之前线程A就已经拥有了该对象的锁)，同时线程A就进入到了该对象的等待池中。
 */
public class WaitNotifyDemo {

    /**
     wait()意思是说，我等会儿再用这把锁，CPU也让给你们，我先休息一会儿！ 释放锁，进入等待池，等待被唤醒
     notify() 唤醒等待中的一个线程，但不会释放锁且会继续执行，唤醒的线程进入锁池参与竞争锁
     * @param args
     */
    public static void main(String[] args){
        final Object object  = new Object();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                synchronized (object){
                    System.out.println("t1 start...");
                    try {
                        //让出锁和cpu 进入object对象的等待池
                        object.wait();
                        System.out.println("t1 end...");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };


        Thread t2 = new Thread(){
            @Override
            public void run() {
                synchronized (object){
                    System.out.println("t2 start");
                    // object.notifyAll();
                    //唤醒object对象的等待池中的所有线程，但不会让出锁，被唤醒的线程进入锁池，当前线程释放锁后，锁池的线程竞争锁，获取锁成功的开始执行
                    object.notifyAll();
                    System.out.println("t2 end...");
                }
            }
        };


        t1.start();
        t2.start();
        //t1 start...
        //t2 start
        //t2 end...
        //t1 end...

        /**
         * T1启动，让出锁，让出CPU，T2获得CPU，启动，唤醒使用了object的休眠的线程，T1被唤醒后等待启动，T2继续执行，T2执行完，T1获得CPU后继续执行。
         值得一提的是，再强调一遍：
         wait会让出CPU而notify不会，notify重在于通知使用object的对象“我用完了！”，wait重在通知其它同用一个object的线程“我暂时不用了”并且让出CPU。
         */
    }
}
